package twel.probenprophet.helden.heroes.helden5;

import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.inject.Inject;

import org.w3c.dom.Element;

import twel.probenprophet.base.enums.Attribute;
import twel.probenprophet.helden.heroes.helden5.jaxb.Hero;
import twel.probenprophet.helden.heroes.helden5.jaxb.SpellSkill;

public class HeroXmlLoader {

	private final XmlReaderHelper helper;

	@Inject
	public HeroXmlLoader(XmlReaderHelper xmlReaderHelper) {
		this.helper = xmlReaderHelper;
	}

	public Hero load(Reader reader) {
		// JAXB does not work for attribute map
		//
		// try {
		// JAXBContext context = JAXBContext.newInstance(HeldenRootElement.class);
		// Unmarshaller unmarshaller = context.createUnmarshaller();
		// HeldenRootElement rootElement = (HeldenRootElement) unmarshaller.unmarshal(reader);
		//
		// return rootElement.getHeroes();
		// } catch (JAXBException e) {
		// throw new ProbenprophetException("JAXB unmarshalling failed", e);
		// }

		Element rootElement = helper.getRootElement(reader);
		Element heroElement = helper.getSingleChild(rootElement, "held");

		return constructHero(heroElement);
	}

	private Hero constructHero(Element heroElement) {
		Hero hero = new Hero();

		hero.setName(heroElement.getAttribute("name"));
		hero.setAttributes(getAttributeMap(heroElement));
		hero.setSpellSkills(getSpellSkills(heroElement));

		return hero;
	}

	private Map<Attribute, Integer> getAttributeMap(Element heroElement) {
		Map<Attribute, Integer> attributeMap = new HashMap<Attribute, Integer>();

		Collection<Element> children = helper.getChildrenInWrapperElement(heroElement, "eigenschaft", "eigenschaften");
		for (Element attributeElement : children) {
			addAttributeEntryToMap(attributeMap, attributeElement);
		}

		return attributeMap;
	}

	private void addAttributeEntryToMap(Map<Attribute, Integer> attributeMap, Element attributeElement) {
		String nameAttribute = attributeElement.getAttribute("name");
		String valueAttribute = attributeElement.getAttribute("value");
		Integer value = Integer.valueOf(valueAttribute);

		Attribute attribute = Attribute.byGermanName(nameAttribute);
		if (attribute != null) {
			attributeMap.put(attribute, value);
		}
	}

	private Collection<SpellSkill> getSpellSkills(Element heroElement) {
		Collection<SpellSkill> spellSkills = new ArrayList<SpellSkill>();

		Collection<Element> children;
		try {
			children = helper.getChildrenInWrapperElement(heroElement, "zauber", "zauberliste");
		} catch (IllegalStateException e) {
			return null;
		}

		for (Element spellSkillElement : children) {
			addSpellSkillToList(spellSkills, spellSkillElement);
		}

		return spellSkills;
	}

	private void addSpellSkillToList(Collection<SpellSkill> spellSkills, Element spellSkillElement) {
		String spellName = spellSkillElement.getAttribute("name");
		String valueAttribute = spellSkillElement.getAttribute("value");
		Integer value = Integer.valueOf(valueAttribute);

		SpellSkill spellSkill = new SpellSkill(spellName, value);
		spellSkills.add(spellSkill);
	}
}
